
%include "arch.s"

section .data

format	db "[asm] Address: %d\n", 0	
	
section	.text
	
global	_vm_asm_dot:function
global	_vm_asm_add:function
global  _vm_asm_sub:function
global	_vm_asm_scale:function
global	_vm_asm_magnitude:function
global	_vm_asm_norm:function
global	_vm_asm_project:function
	
extern	_print_vec
extern	_print_addr
extern	_print_double
extern	_print_xmm_reg

	;;
	;; C function equivalents:
	;; 	void _vm_asm_add(vm_vector *a, vm_vector *b);
	;; 	void _vm_asm_sub(vm_vector *a, vm_vector *b);
	;; These functions put the addition/subtraction of a and b into a.
	
_vm_asm_add:
	movupd	xmm0, [rdi]
	movupd	xmm1, [rdi+16]

	addpd	xmm0, [rsi]
	addpd	xmm1, [rsi+16]
	
	movupd	[rdi], xmm0
	movupd	[rdi+16], xmm1
	ret

_vm_asm_sub:
	movupd	xmm0, [rdi]
	movupd	xmm1, [rdi+16]

	subpd	xmm0, [rsi]
	subpd	xmm1, [rsi+16]
	
	movupd	[rdi], xmm0
	movupd	[rdi+16], xmm1
	ret

	;;
	;; C function equivalent:
	;; 	double _vm_asm_dot(vm_vector *a, vm_vector *b);
	;; This function puts the dot product of a and b in the supplied
	;; pointer.
	;;

_vm_asm_dot:
	movupd	xmm0, [rdi]
	movupd	xmm1, [rdi+16]

 	mulpd	xmm0, [rsi]
	mulpd	xmm1, [rsi+16]
	addpd	xmm0, xmm1

	movhpd	[rsp-8], xmm0
	addsd	xmm0, [rsp-8]
	ret

	;;
	;;  C function equivalent:
	;; 	void scale(vm_vector *, double *, vm_vector *);
	;; Scales the passed vector by some amount.
	;;
	
_vm_asm_scale:
	;; Get the double into both top and bottom of xmm1
	movlpd	xmm1, [rsi]
	movhpd	xmm1, [rsi]
	
	movupd	xmm0, [rdi]
	mulpd	xmm0, xmm1
	movupd	[rdx], xmm0

	movupd	xmm0, [rdi+16]
	mulpd	xmm0, xmm1
	movupd	[rdx+16], xmm0
	ret

	;;
	;; C function equivalent:
	;; 	double _vm_asm_magnitude(vm_vector *);
	;; Returns the magnitude of the vector passed.
	;;

_vm_asm_magnitude:
	preamble
	;sub	rsp, 8
	;mov	rdi, [rsp-24]
	movupd	xmm0, [rdi]
	mulpd	xmm0, xmm0
	call	_print_xmm_reg
	;mov	[rsp-24], rdi
	;add	rsp, 8
	
	;movupd	xmm1, [rdi+8]
	;mulpd	xmm1, xmm1
	;add	rdi, 8
	;call	_print_xmm_reg

	;addpd	xmm0, xmm1
	;movhpd	[rsp-8], xmm0
	;addsd	xmm0, [rsp-8]
	;sqrtsd	xmm0, xmm0
	
	postamble

	;;
	;; C function equivalent:
	;; 	void _vm_asm_norm(vm_vector *, vm_vector *);
	;;
	
one:	dq	1.0
_vm_asm_norm:
	call 	_vm_asm_magnitude
	movsd	xmm1, [one wrt rip wrt ..gotpcrel]
	divsd	xmm1, xmm0
	sub	rsp, 8
	movsd	[rsp], xmm1
	mov	rdx, rsi
	mov	rsi, rsp
	call	_vm_asm_scale
	add	rsp, 8
	ret

	;;
	;; C function equivalent:
	;; 	void _vm_asm_project(vm_vector *a, vm_vector *b, vm_vector *d);
	;; Calculates the projection of a onto b and stores the result in d.
	;;
	
_vm_asm_project:
	push	rdi
	mov	rdi, rsi
	call	_vm_asm_magnitude
	pop	rdi
	mulsd	xmm0, xmm0
	sub	rsp, 8
	movsd	[rsp], xmm0

	mov	rdi, rsp
	call	_print_double
	
	;call	_vm_asm_dot
	;divsd	xmm0, [rsp]
	;movsd	[rsp], xmm0
	;mov	rsi, rsp
	;call	_vm_asm_scale
	;add	rsp, 8
	ret